#ifndef _APP_H_
#define _APP_H_

#include <unordered_map>
#include <string>
#include <vector>
#include "executor.h"
#include "profile.h"
#include "function.h"
#include "queue.hpp" 
#include "memory.h"

namespace sp{

class Function;
class Executor;
class SharedMemoryManager;
class Gpu_SharedMemoryManager;

class App{
private:
    short id;
    std::vector<Executor*> executors;
    std::map<short, std::vector<Function*>> functions_map;  // executor_id到vector<Function*>的映射。
    std::map<short, std::vector<int>> gpus_map;             // gpu_id到executor_id的映射
    std::map<std::string, BlockingQueue<Data*>*> Qs;
    std::vector<BlockingQueue<char>*> controllers;          // 向每个executor发送命令的管道
    std::vector<BlockingQueue<char>*> reporters;            // 从每个executor接收状态的管道
public:
    // App(short id, std::vector<std::tuple<std::string, std::vector<int>, std::vector<int>, std::vector<std::string>, int>>& Fs_table, int max_cores, SharedMemoryManager* sharedMemory, Gpu_SharedMemoryManager* gpu_sharedMemory);
    // App(short id, std::vector<std::tuple<std::string, std::vector<int>, std::vector<int>, std::vector<std::string>, int>>& Fs_table, std::map<int, std::vector<int>>& D_table, SharedMemoryManager* sharedMemory, Gpu_SharedMemoryManager* gpu_sharedMemory);
    App(short id, std::map<short, std::vector<Function*>>& Fs_map, SharedMemoryManager* smm, Gpu_SharedMemoryManager* gpu_smm);
    App(short id, std::map<short, std::vector<Function*>>& Fs_map, SharedMemoryManager* smm, Gpu_SharedMemoryManager* gpu_smm, bool willBindLcore);
    App(short id, std::map<short, std::vector<Function*>>& Fs_map, std::map<short, std::vector<int>>& Gpus_map, SharedMemoryManager* smm, Gpu_SharedMemoryManager* gpu_smm);
    ~App();
    void check();               // 检查Function输入输出关系
    void printMsg();            // 打印Function之间的流关系
    void init();                // 开始App的执行,首先完成初始化
    void run();                 // 进行循环的执行
    void waitForComplete();     // 阻塞当前进程，直到App执行完，并自动进行profile
    short getFirstExecutorId(); // 获取App第一个executor的Id
    short getLastExecutorId();  // 获取App最后一个executor的Id
    int getGpuExecutorCount();  // 得到GpuExecutor的个数
    bool isFirstGpuExecutor(short executor_id);  // 判断此executor是不是第一个GpuExecutor
    bool isLastGpuExecutor(short executor_id);   // 判断此executor是不是最后一个GpuExecutor
    int getBeforeWaitTime(short executor_id);    // 得到此executor在进行GPU显存初始化之前的等待时间
    int getAfterWaitTime(short executor_id);     // 得到此executor在进行GPU显存初始化之后的等待时间
    int getTotalWaitTime();                      // executor初始化的总等待时间
};

};

#endif